﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using MaxLeaf.DB;

using MaxLeaf.Common;
using System.Data.SqlClient;

namespace MaxLeaf.DAL.K3
{
    /// <summary>
    /// 分发基类,add/update/delete
    /// </summary>
    public class BaseDAL : MaxLeaf.DAL.BaseDALBuilder.IDALAction
    {
        public enum GetDataType
        {
            OrgData
            ,DestKeyValue

        }
        //维护表名
        protected string strTableName = null;
        //对应mkeymap使用的key
        protected string strMapKeyFieldName = "FItemID";
        //主key是独立key,还是和其他字段一起组成key
        protected bool blnMapKeyUseOtherKeyFieldsCond =  false;
        //辅助key，就是多字段组成一个key
        protected Dictionary<string, object> dictOtherKeyFieldsCond = null;
        //原始数据和目标数据的辅助key值不一样时用
        protected Dictionary<string, object> dictDestOtherKeyFieldsCond = null;
        //实际数据库key
        protected string strDestRealKeyFieldName = "FNumber";
        //维护的字段，不包括key
        protected string strFieldNames = null;
        //新增时是否填写key值
        protected bool mblnNeedEditKeyValue =true;
        //mapkey是不是自增长的
        protected bool mblnIsIdentity = false;

        /// <summary>
        /// 根据mapkey删除表数据
        /// 如果通过key找不到，表示不是通过程序分发的，忽略
        /// </summary>
        /// <param name="dbOrgCon"></param>
        /// <param name="dbCon"></param>
        /// <param name="strKeyValue"></param>
        public virtual void Delete(DBAccess dbOrgCon, DBAccess dbCon, string strKeyValue)
        {
            DataTable dtKey= DAL_GetData(dbOrgCon,dbCon,(int)GetDataType.DestKeyValue,strKeyValue);
            if (dtKey.Rows.Count == 0)
            {
                return;
            }
            string strDestKeyValue = CvtFunc.ToString(dtKey.Rows[0]["DestKeyValue"]);

            Dictionary<string,object> dictCond=new Dictionary<string,object>(){{strMapKeyFieldName,strDestKeyValue}};
            if (blnMapKeyUseOtherKeyFieldsCond && dictOtherKeyFieldsCond != null)
            {
                foreach (KeyValuePair<string, object> tmp in dictOtherKeyFieldsCond )
                {
                    dictCond.Add(tmp.Key, tmp.Value);
                }
            }
            KeyValuePair<string, IDataParameter[]> kvp = dbCon.CreateCondParam(dictCond);
            string strSql =string.Format( @"delete from {0} where  {1}",strTableName,kvp.Key);            
            dbCon.ExecuteSql(strSql, kvp.Value);
            if (strMapKeyFieldName.Equals("fitemid", StringComparison.InvariantCultureIgnoreCase) &&  GetMapTableName().Equals("t_item", StringComparison.InvariantCultureIgnoreCase))
            {
                //如果填了t_item表，也要一起删除
                kvp = dbCon.CreateCondParam(new Dictionary<string, object>() { { strMapKeyFieldName, strDestKeyValue } });
                strSql = string.Format(@"delete from {0} where  {1}", "t_item", kvp.Key);
                dbCon.ExecuteSql(strSql, kvp.Value);
            }

            if ( strTableName.Equals(GetMapTableName(), StringComparison.InvariantCultureIgnoreCase) || GetMapTableName().Equals("t_item", StringComparison.InvariantCultureIgnoreCase ))
            {

                //删除mapkey
                KeyValuePair<string, IDataParameter[]> kvpParam = dbCon.CreateCondParam( new Dictionary<string,object>(){{"TableName", GetMapTableName() },{"DestKeyValue",strDestKeyValue}});
                dbCon.ExecuteSql(string.Format("delete from mKeyMap where {0}", kvpParam.Key), kvpParam.Value);
            }



        }

        
        /// <summary>
        /// Add没有单独处理,放在update
        /// 每次全部update
        /// </summary>
        /// <param name="dbOrgCon"></param>
        /// <param name="dbCon"></param>
        /// <param name="strKeyValue"></param>
        public virtual void Add(DBAccess dbOrgCon, DBAccess dbCon, string strKeyValue)
        {

            //DataRow drData = dbCon.GetTableDataFirstRow( "mary_goods", new Dictionary<string, object> { { "FItemID", strKeyValue } }, "FItemID");

            //if (drData != null)
            //{
            //    Update(dbCon, drvLog);
            //    return;
            //}

            //string strSql = "insert into mary_goods(FItemID,is_on_sale)  values(?FItemID,0)";
            //SqlParameter[] arrParam = new SqlParameter[] { new SqlParameter("?FItemID", drvLog[DEL.LogDEL.KeyValue]) }; 
            //dbCon.ExecuteSql( strSql, arrParam );

            Update( dbOrgCon,dbCon, strKeyValue);

        }
        //判断原来有没有mapkey,已分发过
        const string TMPDESTKEYVALUE = "-10000";
        string strDestKeyValue = TMPDESTKEYVALUE;

        /// <summary>
        /// 每次全部update
        /// </summary>
        /// <param name="dbOrgCon">来源数据库</param>
        /// <param name="dbDestCon">目标数据库</param>
        /// <param name="strKeyValue"></param>
        public virtual void Update(DBAccess dbOrgCon, DBAccess dbDestCon, string strKeyValue)
        {
            KeyValuePair<string, IDataParameter[]> kvpParam ;
            string strOrgKeyValue = strKeyValue;
            string strUpdateFieldName = strFieldNames;

            #region 根据主帐套fitemid取得分账套fitemid
            DataTable dtKey = DAL_GetData(dbOrgCon, dbDestCon, (int)GetDataType.DestKeyValue, strKeyValue);
            
            strDestKeyValue = TMPDESTKEYVALUE;
            if (dtKey.Rows.Count != 0)
            {
                strDestKeyValue = CvtFunc.ToString(dtKey.Rows[0]["DestKeyValue"]);
            }
            #endregion 根据主帐套fitemid取得分账套fitemid

            kvpParam = CreateKeyParaCond(dbDestCon, strMapKeyFieldName, strDestKeyValue,true );

            DataTable dtData = dbDestCon.GetDataTable( 
                string.Format("select {0} from {1} where {2}"
                        , strMapKeyFieldName + "," + strUpdateFieldName
                        ,strTableName
                        , kvpParam.Key
                        )
                , kvpParam.Value
                );
            DataRow drData = null;
            LogStatus logStatus = LogStatus.Update;

            DataTable dtOrgData=DAL_GetData(dbOrgCon, dbDestCon, (int)GetDataType.OrgData, strOrgKeyValue);
            if(dtOrgData==null  ||dtOrgData.Rows.Count==0)
            {
                return;
            }
            DataRow drOrgData = dtOrgData.Rows[0];


            //如果用keymap找不到,就用第2key(比如fnumber)再对应一次
            if (dtData.Rows.Count == 0  && !string.IsNullOrEmpty(strDestRealKeyFieldName))
            {                
                kvpParam = CreateKeyParaCond(dbDestCon, strDestRealKeyFieldName, CvtFunc.ToString(drOrgData[strDestRealKeyFieldName]),true );

                dtData = dbDestCon.GetDataTable(
                    string.Format("select {0} from {1} where {2}"
                            , strMapKeyFieldName + "," + strUpdateFieldName
                            , strTableName
                            , kvpParam.Key
                            )
                    , kvpParam.Value
                    );                
            }
            if (dtData.Rows.Count == 0)
            {
                //add
                strDestKeyValue = TMPDESTKEYVALUE;

                logStatus = LogStatus.Add;
                drData = dtData.NewRow();
                if (mblnNeedEditKeyValue)
                {
                    DAL_GetFieldData(dbOrgCon, dbDestCon, strMapKeyFieldName, drOrgData, drData);

                    if ((strUpdateFieldName + ",").IndexOf(strMapKeyFieldName + ",", StringComparison.InvariantCultureIgnoreCase) < 0)
                    {
                        strUpdateFieldName = strMapKeyFieldName + "," + strUpdateFieldName;
                    }
                }


                if (dictDestOtherKeyFieldsCond != null)
                {
                    foreach (KeyValuePair<string, object> tmp in dictDestOtherKeyFieldsCond)
                    {
                        drData[tmp.Key] = tmp.Value;
                        if ((strUpdateFieldName + ",").IndexOf(tmp.Key + ",", StringComparison.InvariantCultureIgnoreCase) < 0)
                        {
                            strUpdateFieldName = tmp.Key + "," + strUpdateFieldName;
                        }
                    }
                }
                else if (dictOtherKeyFieldsCond != null)
                {
                    foreach (KeyValuePair<string, object> tmp in dictOtherKeyFieldsCond)
                    {
                       drData[tmp.Key]= tmp.Value;
                       if ((strUpdateFieldName + ",").IndexOf(tmp.Key + ",", StringComparison.InvariantCultureIgnoreCase) < 0)
                       {
                           strUpdateFieldName = tmp.Key + "," + strUpdateFieldName;
                       }
                    }
                }
            }
            else
            {
                drData = dtData.Rows[0];
            }

            //其他字段填值
            string[] arrFieldName = strUpdateFieldName.Split(',');
            foreach (string strField in arrFieldName)
            {
                DAL_GetFieldData(dbOrgCon, dbDestCon, strField, drOrgData, drData);
            }

            Update_Before(dbOrgCon, dbDestCon, drOrgData, drData);

            //add or update
            KeyValuePair<string, IDataParameter[]> kvp = dbDestCon.CreateParamSql(strUpdateFieldName, strTableName, drData, logStatus, strMapKeyFieldName);
            string strIdentity=dbDestCon.GetValue(kvp.Key, kvp.Value);

            if (strDestKeyValue.Equals(TMPDESTKEYVALUE)  )
            {
                //得到mapkey,保存
                
                    kvpParam = CreateKeyParaCond(dbDestCon, strDestRealKeyFieldName, CvtFunc.ToString(drData[strDestRealKeyFieldName]), true);

                    dtData = dbDestCon.GetDataTable(
                        string.Format("select {0} from {1} where {2}"
                                , strMapKeyFieldName
                                , strTableName
                                , kvpParam.Key
                                )
                        , kvpParam.Value
                        );
                    strDestKeyValue = CvtFunc.ToString(dtData.Rows[0][strMapKeyFieldName]);
                
                SaveKeyMap(dbDestCon, strOrgKeyValue, strDestKeyValue);
            }

           
            UpdateOtherData(dbOrgCon, dbDestCon, drOrgData, drData);

        }

        protected virtual void Update_Before(DBAccess dbOrgCon, DBAccess dbCon, DataRow drOrgData, DataRow drData)
        {
             
        }

        protected void SaveKeyMap(DBAccess dbCon, string strOrgKeyValue, string strDestKeyValue)
        {
            string strSql = @"if not exists(select * from mKeyMap where TableName=@TableName and OrgKeyValue=@OrgKeyValue)
            begin
                insert into mKeyMap(TableName,OrgKeyValue,DestKeyValue) 
                values(@TableName,@OrgKeyValue,@DestKeyValue)
            end ";
            KeyValuePair<string, IDataParameter[]> kvpMap = dbCon.CreateCondParam(new Dictionary<string, object> {
                { "TableName", GetMapTableName() }
                , { "OrgKeyValue", strOrgKeyValue }
                , { "DestKeyValue", strDestKeyValue }
            });
            dbCon.ExecuteSql(strSql, kvpMap.Value);
        }

       
        /// <summary>
        /// 更新完主数据，再更新其他数据
        /// </summary>
        /// <param name="dbOrgCon"></param>
        /// <param name="dbCon"></param>
        /// <param name="drOrgData"></param>
        /// <param name="drData"></param>
        protected virtual void UpdateOtherData(DBAccess dbOrgCon, DBAccess dbCon, DataRow drOrgData, DataRow drData)
        {
            
        }

        /// <summary>
        /// 根据主key+辅助key建条件
        /// </summary>
        /// <param name="dbCon"></param>
        /// <param name="strKeyFieldName"></param>
        /// <param name="strDestKeyValue"></param>
        /// <param name="blnDest"></param>
        /// <returns></returns>
        private KeyValuePair<string, IDataParameter[]> CreateKeyParaCond(DBAccess dbCon,string strKeyFieldName, string strDestKeyValue,bool blnDest)
        {
            Dictionary<string, object> dictCond = new Dictionary<string, object>() { { strKeyFieldName, strDestKeyValue } };
            if (!blnMapKeyUseOtherKeyFieldsCond && strKeyFieldName.Equals(strMapKeyFieldName, StringComparison.InvariantCultureIgnoreCase))
            {
            }
            else
            {
                if (blnDest && dictDestOtherKeyFieldsCond != null)
                {
                    foreach (KeyValuePair<string, object> tmp in dictDestOtherKeyFieldsCond)
                    {
                        dictCond.Add(tmp.Key, tmp.Value);
                    }
                }
                else if (dictOtherKeyFieldsCond != null)
                {
                    foreach (KeyValuePair<string, object> tmp in dictOtherKeyFieldsCond)
                    {
                        dictCond.Add(tmp.Key, tmp.Value);
                    }
                }
            }
            KeyValuePair<string, IDataParameter[]> kvp = dbCon.CreateCondParam(dictCond);
            return kvp;
        }

        /// <summary>
        /// 根据FielName赋值
        /// </summary>
        /// <param name="dbOrgCon"></param>
        /// <param name="dbDestCon"></param>
        /// <param name="strFieldName"></param>
        /// <param name="drOrgData"></param>
        /// <param name="drDestData"></param>
        protected virtual void DAL_GetFieldData(DBAccess dbOrgCon, DBAccess dbDestCon, string strFieldName,DataRow drOrgData,DataRow drDestData)
        {
            drDestData[strFieldName] = drOrgData[strFieldName];
        }

        /// <summary>
        /// 获取数据
        /// </summary>
        /// <param name="dbOrgCon"></param>
        /// <param name="destCon"></param>
        /// <param name="intdataType"></param>
        /// <param name="objParam"></param>
        /// <returns></returns>
        protected virtual DataTable DAL_GetData(DBAccess dbOrgCon, DBAccess destCon, int intdataType, object objParam)
        {

            GetDataType dataType = (GetDataType)intdataType;
            if (dataType == GetDataType.DestKeyValue)
            {
                return GetDestKeyValue(dbOrgCon, destCon, CvtFunc.ToString(objParam));
            }
            else if (dataType == GetDataType.OrgData)
            {
                return GetOrgData(dbOrgCon, CvtFunc.ToString(objParam));
            }


            throw new MaxLeafException(string.Format("GetData {0} 没注册", intdataType));

        }

       /// <summary>
       /// 获取来源表数据
       /// </summary>
       /// <param name="dbOrgCon"></param>
       /// <param name="strOrgKeyValue"></param>
       /// <returns></returns>
        private DataTable GetOrgData(DBAccess dbOrgCon, string strOrgKeyValue)
        {
            
                KeyValuePair<string, IDataParameter[]> kvpParam = CreateKeyParaCond(dbOrgCon, strMapKeyFieldName, strOrgKeyValue,false);

               DataTable dtOrgData = dbOrgCon.GetDataTable( 
                string.Format("select {0} from {1} where {2}"
                        , "*"
                        ,strTableName
                        , kvpParam.Key
                        )
                , kvpParam.Value
                );

            
            return dtOrgData;
        }

        /// <summary>
        /// mapkey
        /// </summary>
        /// <param name="dbOrgCon"></param>
        /// <param name="dbCon"></param>
        /// <param name="strOrgKeyValue"></param>
        /// <returns></returns>
        private DataTable GetDestKeyValue(DBAccess dbOrgCon, DBAccess dbCon, string strOrgKeyValue)
        {
            
            return dbCon.GetTableData("mKeyMap", new Dictionary<string, object>() { { "TableName", GetMapTableName() }, { "OrgKeyValue", strOrgKeyValue } }, "DestKeyValue");
        }

        /// <summary>
        /// 如果mapkeyname=fitemid,就都用t_item表
        /// </summary>
        /// <returns></returns>
        protected string GetMapTableName()
        {
            string strMapTableName = strTableName;
            if (strMapKeyFieldName.Equals("FItemID", StringComparison.InvariantCultureIgnoreCase))
            {
                strMapTableName = "t_Item";
            }
            return strMapTableName;
        }

        /// <summary>
        /// 取得mapkey,没有找到就先强制分发一次
        /// </summary>
        /// <param name="dbOrgCon"></param>
        /// <param name="dbDestCon"></param>
        /// <param name="strOrgKeyValue"></param>
        /// <returns></returns>
        public virtual string GetDestMapKeyValue(DBAccess dbOrgCon, DBAccess dbDestCon, string strOrgKeyValue)
        {
            if (dbDestCon.ServerMasterDB)
            {
                //如果是主帐套，就是原始值
                return strOrgKeyValue;
            }
            KeyValuePair<string, IDataParameter[]> kvp = dbDestCon.CreateCondParam(new Dictionary<string, object>() { { "TableName", GetMapTableName() }, { "OrgKeyValue", strOrgKeyValue } });
            string strSql = string.Format("select DestKeyValue from mkeymap where {0}", kvp.Key);

            string strDestMapKeyValue = dbDestCon.GetValue(strSql, kvp.Value);
            if (strDestMapKeyValue.Length > 0)
            {
                return strDestMapKeyValue;
            }

            Update(dbOrgCon, dbDestCon, strOrgKeyValue);

            kvp = dbDestCon.CreateCondParam(new Dictionary<string, object>() { { "TableName", GetMapTableName() }, { "OrgKeyValue", strOrgKeyValue } });
            return dbDestCon.GetValue(strSql, kvp.Value);
        }


        /// <summary>
        /// 取得mapkey,没有找到就先强制分发一次
        /// </summary>
        /// <param name="dbOrgCon"></param>
        /// <param name="dbDestCon"></param>
        /// <param name="strOrgKeyValue"></param>
        /// <returns></returns>
        public virtual string GetOrgMapKeyValue(DBAccess dbOrgCon, DBAccess dbDestCon, string strDestKeyValue)
        {
            if (dbDestCon.ServerMasterDB)
            {
                //如果是主帐套，就是原始值
                return strDestKeyValue;
            }

            KeyValuePair<string, IDataParameter[]> kvp = dbDestCon.CreateCondParam(new Dictionary<string, object>() { { "TableName", GetMapTableName() }, { "DestKeyValue", strDestKeyValue } });
            string strSql = string.Format("select OrgKeyValue from mkeymap where {0}", kvp.Key);

            return dbDestCon.GetValue(strSql, kvp.Value);
            
        }
    }
}
